package cbfg.common.webview;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.view.KeyEvent;
import android.webkit.ConsoleMessage;
import android.webkit.PermissionRequest;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class WebHookDispatcher extends SimpleWebHook {

    private boolean hasInit = false;

    /**
     * 因为shouldInterceptRequest是一个异步的回调，所以这个类需要加锁
     */
    private final List<WebHook> webHooks = new CopyOnWriteArrayList<>();

    public void addWebHook(WebHook webHook) {
        webHooks.add(webHook);
        if (hasInit) {
            webHook.onWebInit(mWebView);
        }
    }

    public void addWebHooks(Collection<WebHook> webHooks) {
        this.webHooks.addAll(webHooks);
        if (hasInit) {
            for (WebHook webHook : webHooks) {
                webHook.onWebInit(mWebView);
            }
        }
    }

    public void addWebHook(int position, WebHook webHook) {
        webHooks.add(position, webHook);
        if (hasInit) {
            webHook.onWebInit(mWebView);
        }
    }

    public void addWebHooks(int position, Collection<WebHook> webHooks) {
        this.webHooks.addAll(position, webHooks);
        if (hasInit) {
            for (WebHook webHook : webHooks) {
                webHook.onWebInit(mWebView);
            }
        }
    }

    @Nullable
    public WebHook findWebHookByClass(Class<? extends WebHook> clazz) {
        for (WebHook webHook : webHooks) {
            if (webHook.getClass().equals(clazz)) {
                return webHook;
            }
        }
        return null;
    }

    public void removeWebHook(WebHook webHook) {
        webHooks.remove(webHook);
    }

    @NonNull
    public List<WebHook> getWebHooks() {
        return webHooks;
    }

    public void clear() {
        webHooks.clear();
    }

    //dispatch method ----------------

    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        for (WebHook webHook : webHooks) {
            if (webHook.shouldOverrideUrlLoading(webView, url)) {
                return true;
            }
        }
        return super.shouldOverrideUrlLoading(webView, url);
    }


    @Override
    public void onPageFinished(WebView webView, String url) {
        for (WebHook webHook : webHooks) {
            webHook.onPageFinished(webView, url);
        }
    }

    @Override
    public void onReceivedTitle(WebView webView, String title) {
        for (WebHook webHook : webHooks) {
            webHook.onReceivedTitle(webView, title);
        }
    }

    @Override
    public void onProgressChanged(WebView webView, int newProgress) {
        for (WebHook webHook : webHooks) {
            webHook.onProgressChanged(webView, newProgress);
        }
    }

    @Override
    public void onPageStarted(WebView webView, String url, Bitmap favicon) {
        for (WebHook webHook : webHooks) {
            webHook.onPageStarted(webView, url, favicon);
        }
    }


    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                                     WebChromeClient.FileChooserParams fileChooserParams) {
        for (WebHook webHook : webHooks) {
            if (webHook.onShowFileChooser(webView, filePathCallback, fileChooserParams)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
        for (WebHook webHook : webHooks) {
            if (webHook.onActivityResult(requestCode, resultCode, intent)) {
                return true;
            }
        }
        return false;
    }


    @Override
    public void onReceivedError(WebView webView, WebResourceRequest request, WebResourceError error) {
        for (WebHook webHook : webHooks) {
            webHook.onReceivedError(webView, request, error);
        }
    }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        for (WebHook webHook : webHooks) {
            WebResourceResponse response = webHook.shouldInterceptRequest(view, request);
            if (response != null) {
                return response;
            }
        }
        return super.shouldInterceptRequest(view, request);
    }

    @Override
    public boolean onBackPressed() {
        for (WebHook webHook : webHooks) {
            if (webHook.onBackPressed()) {
                return true;
            }
        }
        return super.onBackPressed();
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        for (WebHook webHook : webHooks) {
            if (webHook.onKeyUp(keyCode, event)) {
                return true;
            }
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public void onConsoleMessage(ConsoleMessage consoleMessage) {
        for (WebHook webHook : webHooks) {
            webHook.onConsoleMessage(consoleMessage);
        }
    }

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        for (WebHook webHook : webHooks) {
            webHook.onReceivedSslError(view, handler, error);
        }
        super.onReceivedSslError(view, handler, error);
    }

    @Override
    public void onReceivedError(WebView webView, String url, int errorCode, String description) {
        for (WebHook webHook : webHooks) {
            webHook.onReceivedError(webView, url, errorCode, description);
        }
        super.onReceivedError(webView, url, errorCode, description);
    }


    @Override
    public void onPermissionRequest(PermissionRequest request) {
        super.onPermissionRequest(request);
        for (WebHook webHook : webHooks) {
            webHook.onPermissionRequest(request);
        }
    }
    // ...其余回调代码省略
}
